package Threads.extra;

import redis.clients.jedis.Jedis;

import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicIntegerArray;

//使用jedis连接redis
public class jedis {
    public static void main(String[] args) throws InterruptedException {
            jedis_pool_factory jedis_pool_factory=new jedis_pool_factory();
            //most processors
            int count = Runtime.getRuntime().availableProcessors();
            jedis.jedis_pool_factory.jedis_pool jedis_pool = jedis_pool_factory.getJedis_pool(count);
            long start = System.nanoTime();
             for (int i=0;i<100;i++){
                new Thread(()->{
                    int temp=new Random().nextInt(10);
                    Jedis jedis = jedis_pool.getJedis();
                    jedis.lpush("jedis",Thread.currentThread().getName());
                    jedis_pool.putJedis(jedis);
                }).start();
            }
            long end= System.nanoTime();
            System.out.println((end-start)/1000000+"ms");
            //get the info of list jedis,also can see in redis
            /*Thread.sleep(1000);
            List<String> jedis = jedis_pool.getJedis().lrange("jedis", 0, -1);
            for (String s:jedis)
                System.out.println(s);*/


    }


    //使用单例模式（dcl）获取唯一的线程池
    static class jedis_pool_factory{
        private volatile jedis_pool jedis_pool=null;
        private final Object lock=new Object();

        public jedis_pool_factory(){}


        //make jedis_pool singleton(dcl)
        public jedis_pool getJedis_pool(int poolsize) {
            if (jedis_pool==null){
                synchronized (lock){
                    if (jedis_pool==null)
                        jedis_pool=new jedis_pool(poolsize);
                }
            }
            return jedis_pool;
        }

        //内部类
        private static class jedis_pool {
            //numbers of conneciton
            private final int poolSize;
            //store redis connection
            private final Jedis[] jedis_array;
            //store the state of the connection
            private final AtomicIntegerArray states;

            //details of connection
            private final static String url;
            private final static int port;

            static {
                url = "localhost";
                port = 6379;
            }

            //create the jedis pool
            private jedis_pool(int poolsize) {
                this.poolSize = poolsize;
                jedis_array = new Jedis[poolsize];
                states = new AtomicIntegerArray(poolsize);
                for (int i = 0; i < poolsize; i++) {
                    jedis_array[i] = new Jedis(url, port);
                }
            }

            //getConnetion
            public Jedis getJedis() {
                while (true) {
                    //try to get the connection
                    for (int i = 0; i < poolSize; i++) {
                        if (states.get(i) == 0) {
                            if (states.compareAndSet(i, 0, 1)) {
                                return jedis_array[i];
                            }
                        }
                    }
                    //wait
                    synchronized (this) {
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

            //return the connection
            public void putJedis(Jedis jedis) {
                for (int i = 0; i < poolSize; i++) {
                    if (jedis_array[i] == jedis) {
                        states.set(i, 0);
                    }
                }
                synchronized (this) {
                    this.notifyAll();
                }
            }
        }
    }
}
